﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityChan;
using System;

public class HairUnitEmitter : MonoBehaviour
{
    public GameObject unitPrefab;
    public Mesh[] endTypeMeshs;
    public SkinnedMeshRenderer[] endTypeSMRs;
    public Mesh customMesh;
    public int segment;
    public List<HairUnit> hairUnits;
    public Vector3 unitScale;
    public SpringGenerator generator;
    private const int opNone = 0;
    private const int opAdd = 1;
    private const int opRemove = 2;
    public int mouseDragOperation; // 0 None 1 Add 2 Remove
    public SliderMgr sdMgr;
    public RandomWind wind;
    public HairUnitScaler scaler;
    public const int sub = 0;
    public const int add = 1;
    public int selectOp = add;
    public const int one = 0;
    public const int two = 1;
    public int handMode = 0;
    public RectTransform[] clickBlocks;
    public LabelSlider newAngleSlider;
    public Vector3 newAngleMOM;
    void OnAngleSliderChanged(float v)
    {
        if (sdMgr.ignoreValueChanges || scaler.unitsSelected.Count == 0) return;
        var u0 = scaler.unitsSelected[scaler.unitsSelected.Count - 1];
        var os = v - u0.transform.localEulerAngles.y;
        foreach (var u in scaler.unitsSelected)
        {
            var y = u.transform.localEulerAngles.y;
            y += os;
            y = Mathf.Repeat(y, 360);
            u.transform.localEulerAngles = u.transform.localEulerAngles.SetY(y);
            u.UpdateColliderAndSectionTrans();
        }
    }
    private void Update()
    {
        if (sdMgr.manualGizmos.gameObject.activeInHierarchy) return;
        if (hairUnits.Count == 0 || wind.isWindActive) return;

        foreach (var block in clickBlocks)
        {
            if (RectTransformUtility.RectangleContainsScreenPoint(block, Input.mousePosition)) return;
        }

        var shift = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
        var ctrl = Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl);
        var click = Input.GetMouseButtonDown(0);
        var drag = Input.GetMouseButton(0);
        if (!click && !drag) return;
        int mask = 1 << LayerMask.NameToLayer("Hairs");
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        RaycastHit hit;
        bool bHit = Physics.Raycast(ray, out hit, Mathf.Infinity, mask, QueryTriggerInteraction.Collide);
        if (bHit)
        {
            var ivc = sdMgr.ignoreValueChanges;
            sdMgr.ignoreValueChanges = true;
            int index = -1;
            var smrSelected = hit.transform.GetComponent<SkinnedMeshRenderer>();
            for (int i = 0; i < hairUnits.Count; i++)
            {
                var unit = hairUnits[i];
                if (unit.smr == smrSelected) // 点击到或者拖选到的发束
                {
                    if (click && !shift && !ctrl)
                    {
                        // 双手模式下， 没按shift和Ctrl的点击，单选发束
                        if (handMode == two)
                        {
                            if (!(scaler.unitsSelected.Contains(unit) && scaler.unitsSelected.Count == 1))
                            {
                                scaler.unitsSelected.Clear();
                                scaler.unitsSelected.Add(unit); // 清空其他，留下单个选项
                                index = i + 1;
                                sdMgr.hairSelector.value = index; // 改变值，调用选择更改callback
                            }
                        }
                        else // 单手模式
                        {
                            if (scaler.unitsSelected.Count == 0)//0个选项时加选
                            {
                                selectOp = add;
                                scaler.unitsSelected.Add(unit);
                                index = i + 1;
                                sdMgr.hairSelector.value = index; // 改变值，调用选择更改callback
                            }
                            else if (scaler.unitsSelected.Count == hairUnits.Count)//全选时减选
                            {
                                selectOp = sub;
                                scaler.unitsSelected.Remove(unit);
                                if (scaler.unitsSelected.Count > 0)
                                    index = 1;
                                else index = 0;
                                sdMgr.hairSelector.value = index;
                            }
                            else if (scaler.unitsSelected.Count == 1)
                            {
                                if (!scaler.unitsSelected.Contains(unit))// 选项为1时反转操作
                                {
                                    selectOp = add;
                                }
                                else
                                {
                                    selectOp = sub;
                                }
                            }
                            else if (scaler.unitsSelected.Contains(unit))
                            {
                                selectOp = add;
                            }
                            else
                            {
                                selectOp = sub;
                            }
                        }
                    }
                    else if (shift) // 按住shift的点击或拖曳，加选 
                    {
                        selectOp = add;
                        if (!scaler.unitsSelected.Contains(unit))// 前提是点击到没选的发束
                        {
                            scaler.unitsSelected.Add(unit);
                            index = i + 1;
                            sdMgr.hairSelector.value = index; // 改变值，调用选择更改callback
                        }
                    }
                    else if (ctrl) // 按住Ctrl的点击或拖曳，减选
                    {
                        if (scaler.unitsSelected.Contains(unit))
                        {
                            scaler.unitsSelected.Remove(unit); // 多于一个则减选,当前选择变为选择里的第一个
                            if (scaler.unitsSelected.Count > 0)
                                index = 1;
                            else index = 0;
                            sdMgr.hairSelector.value = index;
                        }
                    }
                    else //if (!click)// 没按shift和ctrl的拖曳
                    {
                        if (handMode == one) // 单手模式下根据前一个操作选择加选或减选，双手模式无视
                        {
                            if (selectOp == add)
                            {
                                if (!scaler.unitsSelected.Contains(unit))
                                {
                                    scaler.unitsSelected.Add(unit);
                                    index = i + 1;
                                    sdMgr.hairSelector.value = index;
                                }
                            }
                            else // sub
                            {
                                if (scaler.unitsSelected.Contains(unit))
                                {
                                    scaler.unitsSelected.Remove(unit);
                                    if (scaler.unitsSelected.Count > 0)
                                        index = 1;
                                    else index = 0;
                                    sdMgr.hairSelector.value = index;
                                }
                            }
                        }
                    }
                }
                if (scaler.unitsSelected.Count > 0 && index != -1)
                {
                    var u = sdMgr.emitter.hairUnits[index - 1];
                    newAngleSlider.value = u.transform.localEulerAngles.y;
                    sdMgr.GetUnitValueToUI(u);
                    if (sdMgr.manualSectionPosOn)
                    {
                        sdMgr.ShowManualSectionPosGizmos();
                    }
                }
            }
            RefreshCullingObjects();
            sdMgr.ignoreValueChanges = ivc;
        }
    }
    public void RefreshCullingObjects()
    {
        CullObject.I.gos.Clear();
        foreach (var unit in hairUnits)
        {
            if (scaler.unitsSelected.Contains(unit))
            {
                CullObject.I.gos.Add(unit.smr.gameObject);
            }
        }
    }
    private void Awake()
    {
        generator = GetComponent<SpringGenerator>();
        var mgrs = GetComponentsInChildren<SpringManager>(true);
        foreach (var mgr in mgrs)
        {
            generator.Generate(mgr.transform);
        }
        for (int i = 0; i < endTypeMeshs.Length; i++)
        {
            endTypeMeshs[i] = Instantiate(endTypeMeshs[i]);
        }
        unitPrefab.SetActive(false);
        scaler = GetComponentInChildren<HairUnitScaler>();
        sdMgr = GetComponentInChildren<SliderMgr>();
        wind = GetComponent<RandomWind>();
        var o = sdMgr.ignoreValueChanges;
        sdMgr.ignoreValueChanges = true;
        scaler.Init();
        newAngleSlider.Init(newAngleMOM, OnAngleSliderChanged);
        sdMgr.ignoreValueChanges = o;
    }
    public void ClearUnits()
    {
        sdMgr.hairSelector.value = 0;
        foreach (var hair in hairUnits)
        {
            Destroy(hair.gameObject);
        }
        hairUnits.Clear();
    }
    public void DeleteUnit()
    {
        var sel = new List<HairUnit>(scaler.unitsSelected);
        sdMgr.hairSelector.value = 0;
        var n = new List<HairUnit>();
        foreach (var unit in hairUnits)
        {
            if (sel.Contains(unit))
            {
                Destroy(unit.gameObject);
            }
            else n.Add(unit);
        }
        hairUnits = n;
    }
    public void NewUnit()
    {
        var shift = Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift);
        var angle = newAngleSlider.value;
        var n = NewUnitAngle(angle);
        if (shift)
        {
            var m = NewUnitAngle(360 - angle);
            m.mirror = n;
            n.mirror = m;
        }
    }
    internal void DuplicateUnits()
    {
        var dPairs = new Dictionary<HairUnit, HairUnit>();
        foreach (var u in scaler.unitsSelected)
        {
            var go = Instantiate(u.gameObject, transform);
            var n = go.GetComponent<HairUnit>();
            hairUnits.Add(n);
            dPairs.Add(u, n);
        }
        scaler.unitsSelected.Clear();
        foreach (var d in dPairs)
        {
            var n = d.Value;
            foreach (var o in dPairs)
            {
                if (n.mirror == o.Key) // 如果镜像的对象在新复制的队列里
                {
                    n.mirror = o.Value; //建立镜像链接到新的对象
                    goto foundPair;
                }
            }
            n.mirror = null;
            foundPair:
            scaler.unitsSelected.Add(n);
        }

    }
    HairUnit NewUnitAngle(float angle)
    {
        unitPrefab.SetActive(true);
        var n = Instantiate(unitPrefab, transform);
        n.name = "_HairUnit_" + hairUnits.Count.ToString();
        n.transform.Rotate(Vector3.up, angle);
        var unit = n.GetComponent<HairUnit>();
        hairUnits.Add(unit);
        unit.Init();
        unit.UpdateColliderAndSectionTrans();
        unitPrefab.SetActive(false);
        sdMgr.ApplyUIValueToHair(unit);
        sdMgr.hairSelector.maxValue = hairUnits.Count + 1;
        sdMgr.hairSelector.value = hairUnits.Count;
        return unit;
    }
    internal void ReleaseMirrorConnect()
    {
        foreach (var u in scaler.unitsSelected)
        {
            BreakMirrorConnect(u);
        }
    }
    internal void CreateMirrorConnect()
    {
        if (scaler.unitsSelected.Count == 2)
        {
            MakeMirrorConnect(scaler.unitsSelected[0], scaler.unitsSelected[1]);
        }
    }
    void BreakMirrorConnect(HairUnit a)
    {
        if (a.mirror != null)
        {
            a.mirror.mirror = null;
            a.mirror = null;
        }
    }
    void MakeMirrorConnect(HairUnit a, HairUnit b)
    {
        if (a.mirror != null) a.mirror.mirror = null;
        if (b.mirror != null) b.mirror.mirror = null;
        a.mirror = b;
        b.mirror = a;
    }
    public void Emit()
    {
        Emit(segment);
    }
    public void Emit(int segment)
    {
        sdMgr.hairSelector.value = 0; // 先清空选项，避免其他脚本引用出错（CullObject.cs:41）
        sdMgr.manualSectionPosToggle.isOn = false;
        sdMgr.ignoreValueChanges = true;
        if (GetComponent<RandomWind>().isWindActive)
        {
            var t = GameObject.Find("WindToggle").GetComponentInChildren<UnityEngine.UI.Toggle>();
            if (t.isOn) t.isOn = false;
        }
        ClearUnits();
        float factor, angle;
        GameObject n;
        unitPrefab.SetActive(true);
        for (int i = 0; i < segment; i++)
        {
            factor = (float)i / segment;
            angle = 360f * factor;
            n = Instantiate(unitPrefab, transform);
            n.name = "_HairUnit_" + i.ToString();
            n.transform.Rotate(Vector3.up, angle);
            var unit = n.GetComponent<HairUnit>();
            hairUnits.Add(unit);
            unit.Init();
            unit.UpdateColliderAndSectionTrans();
        }
        var half = (int)(segment * 0.5f); // set mirrorunit
        for (int i = 1; i < segment; i++)
        {
            if (i < half)
            {
                hairUnits[i].mirror = hairUnits[segment - i];
                hairUnits[segment - i].mirror = hairUnits[i];
            }
        }
        unitPrefab.SetActive(false);
        sdMgr.ignoreValueChanges = false;
        foreach (var unit in hairUnits)
        {
            sdMgr.ApplyUIValueToHair(unit);
        }
        sdMgr.CallUIOnChanged();
        sdMgr.hairSelector.maxValue = segment + 1;
        sdMgr.hairSelector.value = 0;
        sdMgr.OnHairSelectionChanged(0);//防止本来就是0
    }
}
